package com.tannuo.dolphinnotedemo.sdk.device.protocol;


import com.tannuo.dolphinnotedemo.sdk.util.DataUtil;
import com.tannuo.dolphinnotedemo.sdk.util.Logger;

import java.nio.ByteBuffer;

/**
 * Created by hucn on 2016/7/28.
 * Description: 自定义的协议
 */
public class ZDProtocol extends ProtocolBase {

    private static final String TAG = ZDProtocol.class.getSimpleName();

    // 点的落笔，滑动、抬起的标志位
    public static final byte ACTION_DOWN = (byte) 0x03; // 落下
    public static final byte ACTION_MOVE = (byte) 0x00; // 移动
    public static final byte ACTION_UP = (byte) 0x0C; // 抬起


    @Override
    public IMessage decode(byte[] data) {
        if (null == data || data.length == 0) {
            throw new IllegalArgumentException();
        }

        IMessage msg = new ZDMessage();

        ByteBuffer msgBuffer = ByteBuffer.wrap(data);

        byte[] header = new byte[ProtocolCode.LENGTH_HEADER];
        msgBuffer.get(header, 0, header.length);
        if (header[0] != ProtocolCode.MESSAGE_HEADER[0] || header[1] != ProtocolCode.MESSAGE_HEADER[1]) {
            msg.setFeature(ERROR_HEADER);
            return msg;
        }

        byte[] feature = new byte[ProtocolCode.LENGTH_FEATURE];
        msgBuffer.get(feature, 0, feature.length);
        if (feature[0] == (byte) 0x00) {
            msg.setFeature(ERROR_DATA_FEATURE);
            return msg;
        }

        byte[] id = new byte[ProtocolCode.LENGTH_ID];
        msgBuffer.get(id, 0, id.length);
        if (id[0] == (byte) 0x00 && id[1] == (byte) 0x00) {
            msg.setFeature(ERROR_ID);
            return msg;
        }

        byte[] length = new byte[ProtocolCode.LENGTH_DATA_SIZE];
        msgBuffer.get(length, 0, length.length);
        int dataLength = DataUtil.bytesToIntLittleEndian(length);

        boolean checkLengthResult = checkLength(length, data);
        if (!checkLengthResult) {
            msg.setFeature(ERROR_DATA_LENGTH);
            return msg;
        }

        byte[] content = new byte[dataLength];
        msgBuffer.get(content, 0, content.length);

        byte[] checkDigit = new byte[ProtocolCode.LENGTH_CHECKSUM];
        msgBuffer.get(checkDigit, 0, checkDigit.length);
        if (!checkDigit(checkDigit, data)) {
            msg.setFeature(ERROR_DATA);
            return msg;
        }

        byte[] end = new byte[ProtocolCode.LENGTH_END];
        msgBuffer.get(end, 0, end.length);
        if (end[0] != ProtocolCode.MESSAGE_END[0]) {
            msg.setFeature(ERROR_END);
            return msg;
        }

        boolean checkSumResult = checkSum(data, header, feature, id, length, content, checkDigit, end);
        /*if (!checkSumResult) {
            Logger.e(TAG, "CheckSum error when parsed.");
            msg.setFeature(ERROR_CHECKSUM);
            return msg;
        }*/

        //int result = getFeatureResult(feature);
        msg.setFeature(feature);
        msg.setId(id);
        msg.setData(content);
        Logger.d(TAG, "Parsed byte[] data successfully, return IMessage object to the protocolHandler.");

        return msg;
    }

    @Override
    public byte[] encode(IMessage message) {
        if (message == null) {
            throw new IllegalArgumentException();
        }

        return message.getBytes();
    }

    private boolean checkLength(byte[] length, byte[] data) {
        //// TODO: 2016/7/28 to do the check
        return true;
    }

    private boolean checkSum(byte[] data, byte[] header, byte[] feature, byte[] id, byte[] length, byte[] content, byte[] checkDigit, byte[] end) {
        int totalMessageLength = data.length;
        int countLength = header.length + feature.length + id.length + length.length + content.length + checkDigit.length + end.length;
        return totalMessageLength == countLength;
    }

    private boolean checkDigit(byte[] checkDigit, byte[] data) {
        //// TODO: 2016/7/28 to do the check
        return true;
    }

    private byte[] getcheckDigit(IMessage message) {
        return new byte[]{(byte) 0x00};
    }

    /**
     * 进行编码时获得数据总的长度
     */
    public int getTotalLength(IMessage message) {
        //根据数据域的长度大小赋值
        int totalLength = 0;
        if (message == null) {
            return totalLength;
        }
        int dataLength = getContentLength(message);
        totalLength = dataLength + ProtocolCode.LENGTH_HEADER + ProtocolCode.LENGTH_FEATURE + ProtocolCode.LENGTH_ID +
                ProtocolCode.LENGTH_DATA_SIZE + ProtocolCode.LENGTH_CHECKSUM + ProtocolCode.LENGTH_END;
        return totalLength;
    }

    /**
     * 获取消息内容的长度
     */
    public int getContentLength(IMessage message) {
        int dataLength = 0;
        if (message == null) {
            return dataLength;
        }
        dataLength = message.getData().length;
        return dataLength;
    }

    /**
     * 获取消息的内容
     */
    public byte[] getContent(IMessage message) {
        byte[] content = message.getData();
        return content;
    }

    /**
     * 根据feature获得相应的指令
     */
    private int getFeatureResult(byte[] feature) {
        int cmd = ERROR_NONE;
        switch (feature[0]) {
            case ProtocolCode.ACTION_REQUEST_SNAPSHOT:
                cmd = ProtocolBase.STATUS_REQUEST_SNAPSHOT;
                break;
            case ProtocolCode.ACTION_REQUEST_TO_DISCONNECT:
                cmd = ProtocolBase.STATUS_REQUEST_TO_DISCONNECT;
                break;
            case ProtocolCode.ACTION_REQUEST_TO_REPEAT:
                cmd = ProtocolBase.STATUS_REQUEST_TO_REPEAT;
                break;
            case ProtocolCode.ACTION_RESERVE_01:

                break;
            case ProtocolCode.ACTION_RESERVE_02:

                break;
            case ProtocolCode.ACTION_RESERVE_03:

                break;
            case ProtocolCode.ACTION_RESPONSE_RECEIVED:
                cmd = ProtocolBase.STATUS_RESPONSE_RECEIVED;
                break;
            case ProtocolCode.ACTION_REQUEST_HARDWARE:
                cmd = ProtocolBase.STATUS_REQUEST_HARDWARE;
                break;
            case ProtocolCode.ACTION_REQUEST_CURRENT_RECORD_STATUS:
                cmd = ProtocolBase.STATUS_REQUEST_CURRENT_RECORD_STATUS;
                break;
            case ProtocolCode.ACTION_BEAT:
                cmd = ProtocolBase.STATUS_BEAT;
                break;
            case ProtocolCode.FUNC_REQUEST_SNAPSHOT_INFO:
                cmd = ProtocolBase.STATUS_REQUEST_SNAPSHOT_INFO;
                break;
            case ProtocolCode.FUNC_REQUEST_START_RECORDING:
                cmd = ProtocolBase.STATUS_REQUEST_START_RECORDING;
                break;
            case ProtocolCode.FUNC_REQUEST_STOP_RECORDING:
                cmd = ProtocolBase.STATUS_REQUEST_STOP_RECORDING;
                break;
            case ProtocolCode.FUNC_REQUEST_TIME_REVISION:
                cmd = ProtocolBase.STATUS_REQUEST_TIME_REVISION;
                break;
            case ProtocolCode.FUNC_RESPONSE_TIME_REVISION:
                cmd = ProtocolBase.STATUS_REQUEST_SNAPSHOT;
                break;
            case ProtocolCode.FUNC_REQUEST_CONNECTING:
                cmd = ProtocolBase.STATUS_RESPONSE_TIME_REVISION;
                break;
            case ProtocolCode.FUNC_RESPONSE_CONNECTING_SUCCESS:
                cmd = ProtocolBase.STATUS_RESPONSE_CONNECTING_SUCCESS;
                break;
            case ProtocolCode.FUNC_RESPONSE_CONNECTING_ERROR:
                cmd = ProtocolBase.STATUS_RESPONSE_CONNECTING_ERROR;
                break;
            case ProtocolCode.FUNC_RESPONSE_ERROR:
                cmd = ProtocolBase.STATUS_RESPONSE_ERROR;
                break;
            case ProtocolCode.FUNC_REQUEST_INFO_CONTROL:
                cmd = ProtocolBase.STATUS_REQUEST_INFO_CONTROL;
                break;
            case ProtocolCode.FUNC_RESPONSE_CURRENT_RECORD_STATUS:
                cmd = ProtocolBase.STATUS_RESPONSE_CURRENT_RECORD_STATUS;
                break;
            case ProtocolCode.FUNC_RESPONSE_HARDWARE:
                cmd = ProtocolBase.STATUS_RESPONSE_HARDWARE;
                break;
            case ProtocolCode.FUNC_RESPONSE_SCREEN:
                cmd = ProtocolBase.STATUS_RESPONSE_SCREEN;
                break;
            case ProtocolCode.FUNC_REQUEST_SET_QR_CODE:
                cmd = ProtocolBase.STATUS_REQUEST_SET_QR_CODE;
                break;
            case ProtocolCode.FUNC_REQUEST_SET_SCREEN:
                cmd = ProtocolBase.STATUS_REQUEST_SET_SCREEN;
                break;
            case ProtocolCode.FUNC_REQUEST_SET_THRESHOLD:
                cmd = ProtocolBase.STATUS_REQUEST_SET_THRESHOLD;
                break;
            case ProtocolCode.FUNC_REQUEST_SET_INTERVAL:
                cmd = ProtocolBase.STATUS_REQUEST_SET_INTERVAL;
                break;
            case ProtocolCode.FUNC_POINT_DATA:
                cmd = ProtocolBase.STATUS_POINT_DATA;
                break;
        }
        return cmd;
    }
}
